/***************************************************************************
 创建者: 华磊
 开始时间: 2020.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2020.5.8 类的具体实现代码编写

 ***************************************************************************
 *  @file x.h
 *  功能:
 *
 *                                                                         *
 ***************************************************************************/
#ifndef ECATMASTERBASE_H
#define ECATMASTERBASE_H

#include <pthread.h>
#include "ecatlog.h"
#include "ecattype.h"
#include "MacroDefine/GeneralDefine.h"


////#ifndef error
//#define error     printf
////#endif
////#ifndef message
//#define message    printf
////#endif
///1024
#define DC_FILTER_CNT          1024
#define SYNC_MASTER_TO_REF        1

#define ByteCast(x) ((quint8) (x) & 0x00FF)


class RobotControl;

/**
 * @brief The EcatMasterBase class
 *
 * 使用:主要重写下面的函数以不同支持主站 , 其他函数自行决定
 *
public:
    virtual void stop();
    virtual void start(int us);
    virtual int setAlias( int node , unsigned short alias );
    virtual int sdoUpload()=0;
    virtual int sdoDownload()=0;
    virtual void addMsg(...)=0
protected:

    //at state
    virtual void masterError();
    virtual void masterBootStrap();
    virtual void masterInit();
    virtual void masterPreOp();
    virtual void masterSafeOp();
    virtual void masterOp();

    //状态提升 (不可越级)
    virtual void upgradeState();
    //状态回退：可越级
    virtual void fallbackState();

 */
class RobotBase;
/**
 * @brief The EcatMasterBase class ecat设备基础类
 */
class EcatMasterBase
{
public:

    EcatMasterBase(int pthread_priority_in=50,int pthread_schedule_in=SCHED_RR);
    ~EcatMasterBase();

public:
    int readCheckConfig(QString fileNameIn, int & wkcCheckCountOut, int &periodOut, int &receiveOut, int &sendOut, int &customOut);
    int controllerShutDown();
    bool isSlavesOpStatus();
    bool isInitialOkStatus();
    int setDcTimerShift(int shiftIn);
    int resetMasterTimeMeasure();//没有作用，还是要清空ｔimetool
    int resetMasterStatus();
    int enableSetServoData(bool enable);
    int setServoData(RobotBase* rob);
    int initialServoParameter(RobotBase* rob);

    virtual int stop();
    virtual void start(); //creat and start thread

    virtual bool isRunning(){return isrunning;}
    virtual bool canQuit(){return canquit;}
    //获取主站状态
    virtual E_ECAT_MASTER_STATE getMasterState();
    //切换主站状态
    virtual void setMasterState(E_ECAT_MASTER_STATE cmd);

    /**
      * @brief setAlias  写别名
      * @param node  节点
      * @param alias 具体的别名
      */
    virtual int setAlias( int node , unsigned short alias )=0;
    virtual int sdoUpload(int node
                  ,int rObIndex
                  ,int rObSubIndex
                  ,LONG64 &rData
                  ,int &rDataLen)=0;
    virtual int sdoDownload(int node
                    ,int wObIndex
                    ,int wObSubIndex
                    ,LONG64 wData
                    ,int wDataLen)=0;
    //virtual void getProcessData(char* dataPtr, unsigned int pos, unsigned int bitLen)=0;
    //virtual void setProcessData(char* dataPtr, unsigned int pos, unsigned int bitLen)=0;
    /**
     * @brief addMsg  , 添加消息反馈.会调用继承类的虚函数
     */
    virtual void addMsg(int messageLevel,
                std::string componentName,
                std::string messageType,
                int messageCode,
                int robotId,
                int parameter1=0 ,
                int parameter2=0 ,
                int parameter3=0 ,
                int parameter4=0 )=0;

    /**
     * @brief addMsg  , 添加消息反馈
     */
    void addMsg_base( int messageLevel,
                 std::string componentName,
                 std::string messageType,
                 int messageCode,
                 int robotId,
                 int parameter1 = 0,
                 int parameter2 = 0,
                 int parameter3 = 0,
                 int parameter4 = 0 );

    uint64_t timespec2ns(struct timespec timeSp);

protected:
    int initialTimerMeasurement();
    //thread fun
    virtual void* run(void*);
    //线程回调函数
    static void *threadTask( void* classPtr );

    virtual void osSleepUs(int us);
    virtual void waitNextCycle();
    void wait_period(void);
    uint64_t system_time_ns(void);
    uint64_t system_time_ns_no_plus_base(void);

    struct timespec ns2timespec(uint64_t  timeIn);
    struct timespec timespec_add(struct timespec time1, struct timespec time2);
    uint64_t system2count(uint64_t time);

    //at state
    virtual void masterError()=0;
    virtual void masterBootStrap()=0;
    virtual void masterInit()=0;
    virtual void masterPreOp()
    {//在这个状态退出最好
        if(isShutDown)
            isRun=false;
    }
    virtual void masterSafeOp()=0;
    virtual void masterOp()=0;

    //状态提升 (不可越级)
    virtual void upgradeState();
    //状态回退：可越级
    virtual void fallbackState();

public://仅对ethercat主站公开
    int setDcCycle(int cycleTime);

    virtual void stateMachine( );

    //( t1>t2 )?
    static inline bool tsgreater(struct timespec *t1, struct timespec *t2)
    {
        return ((t1->tv_sec == t2->tv_sec && t1->tv_nsec > t2->tv_nsec) || (t1->tv_sec > t2->tv_sec) );
    }
    //字节转短整形数
    static inline unsigned short bytes_to_uint16( quint8 *b ) {
        unsigned short ret;
        ret = (unsigned short)(ByteCast(b[0]));
        ret |= (unsigned short)(ByteCast(b[1])) << 8;
        return ret;
    }
    //字节转短整形数
    static inline quint32 bytes_to_uint32( quint8 *b ) {
        quint32 ret;
        ret = (quint32)(ByteCast(b[0]));
        ret |= (quint32)(ByteCast(b[1])) << 8;
        ret |= (quint32)(ByteCast(b[2])) << 16;
        ret |= (quint32)(ByteCast(b[3])) << 24;
        return ret;
    }
    //字节转短整形数
    static inline quint64  bytes_to_uint64( quint8 *b ) {
        quint64 ret;
        ret = (quint64)(ByteCast(b[0]));
        ret |= (quint64)(ByteCast(b[1])) << 8;
        ret |= (quint64)(ByteCast(b[2])) << 16;
        ret |= (quint64)(ByteCast(b[3])) << 24;
        ret |= (quint64)(ByteCast(b[4])) << 32;
        ret |= (quint64)(ByteCast(b[5])) << 40;
        ret |= (quint64)(ByteCast(b[6])) << 48;
        ret |= (quint64)(ByteCast(b[7])) << 52;
        return ret;
    }
    //把64位的整数转换成byte型数组
    static inline void uint64_to_bytes(LONG64 i, quint8 *b){
        b[0] = ByteCast(i);
        b[1] = ByteCast(i>>8);
        b[2] = ByteCast(i>>16);
        b[3] = ByteCast(i>>24);
        b[4] = ByteCast(i>>32);
        b[5] = ByteCast(i>>40);
        b[6] = ByteCast(i>>48);
        b[7] = ByteCast(i>>56);
    }
    //把32位的整数转换成byte型数组
//    static inline void uint32_to_bytes(unsigned int i, quint8 *b) {
//        b[0] = ByteCast(i);
//        b[1] = ByteCast(i>>8);
//        b[2] = ByteCast(i>>16);
//        b[3] = ByteCast(i>>24);
//    }

    static inline void uint32_to_bytes(unsigned int i, quint8 *b) {
        b[0] = ((quint8) (i) & 0x000000FF);
        b[1] = ((quint8) (i>>8) & 0x000000FF);
        b[2] = ((quint8) (i>>16) & 0x000000FF);
        b[3] = ((quint8) (i>>24) & 0x000000FF);

    }


    //把16位的整数转换成byte型数组
    static inline void uint16_to_bytes(unsigned short i, quint8 *b) {
        b[0] = ByteCast(i);
        b[1] = ByteCast(i>>8);
    }

protected:
    bool isMasterInit;
    bool isMasterPreOp;
    bool isMasterSafeOp;
    bool isSlavesOp;

    bool isInitialedOk;//hualei 进入了slaves op 才能算初始化完成。以前的第一次报error

    int cycle_us;
    int cycle_ns;
    int dcTimerShift;
    int pthread_priority;
    int pthread_schedule;
    struct timespec cycleTimespec;//周期时间
    //状态/切换
    int masterCurrentState;//当前状态
    int masteroldState;
    volatile int masterCommandState;//目标状态

    //shutDown
    bool isrunning;
    bool isRun;
    bool canquit;
    volatile bool isShutDown;
    pthread_t thId;
    bool setServoDataFlag;

    /****************************************************************************/

    // EtherCAT distributed clock variables

    uint64_t dc_start_time_ns ;
    uint64_t dc_time_ns ;
    #if SYNC_MASTER_TO_REF
    uint8_t  dc_started ;
    int32_t  dc_diff_ns ;
    int32_t  prev_dc_diff_ns ;
    int64_t  dc_diff_total_ns ;
    int64_t  dc_delta_total_ns ;
    int      dc_filter_idx ;
    int64_t  dc_adjust_ns;
    #endif
    int64_t  system_time_base ;
    uint64_t wakeup_time ;
    uint64_t overruns ;


    int cycle_counter;
    unsigned int blink ;


    /*****************************************************************************/

    //time measure
    double ecatPeriodTimerMonitor_now;
    double ecatPeriodTimerMonitor_max;
    double ecatPeriodTimerMonitor_min;
    double ecatReceiveMonitor_now;
    double ecatReceiveMonitor_max;
    double ecatReceiveMonitor_min;
    double ecatSendMonitor_now;
    double ecatSendMonitor_max;
    double ecatSendMonitor_min;
    double ecatCustomMonitor_now;
    double ecatCustomMonitor_max;
    double ecatCustomMonitor_min;

    int min_v_measure[3]={-10000,-20000,-50000};
    int max_v_measure[3]={10000,20000,50000};
    int timer_id_measure[50];

    int timerErrorCount;
    int receiveErrorCount;
    int sendErrorCount;
    int customErrorCount;

    //time limit
    int wkcLostLimit;
    int ecatPeriodTimerOffsetMax;
    int ecatReceiveMax;
    int ecatSendMax;
    int ecatCustomMax;

    int isFristTimeInOp;
    double opLoopCount;







};



#endif // ECATMASTERBASE_H
